#include "solar/trunk/NWidget.h"
#include "solar/beacon/Field.h"
#include "tools/Pyscript.h"
#include "tools/Diary.h"

Nwidget::Nwidget(bool isautoExit, int closewait, QWidget *parent, Qt::WindowFlags flags):QWidget(parent, flags){
    setParent(parent);
    doconfigur_init(isautoExit, closewait);
}


Nwidget::Nwidget(QWidget *parent, Qt::WindowFlags flags):QWidget(parent, flags){
    setParent(parent);
    doconfigur_init(false, 3000);
}


void Nwidget::doconfigur_init(bool autoclose, int closewait){
    setProperty("direction", NT::ORIEN_VERTICAL);
    setProperty("mode-autoclose", autoclose);
    setProperty("mode-autoclosewait", closewait);
    setProperty("back-pixmap-fixedsize", QSize(-10,-10));
    setProperty("back-pixmap-radius", 3);
    setProperty("back-pixmap-hiq", false);
    impact_colorlist["mode-secolor"] = {{QColor(Qt::transparent)}};
    installEventFilter(this);
    connect(&autoTimer, &QTimer::timeout, this, &Nwidget::close);
}


void Nwidget::doconfigur_direction(NT::CST_BRIGHT_SPOT direction){
    setProperty("direction", direction);
}


void Nwidget::doconfigur_autoclose(bool autoclose){
    setProperty("mode-autoclose", autoclose);
    }


void Nwidget::doconfigur_autoclosewait(int closewait){
    setProperty("mode-autoclosewait", closewait);
}


void Nwidget::doconfigur_iserpixmap(QList<std::pair<QString, int>> insert_pixmap){
    impact_istpixmap["InsertPixmap"] = insert_pixmap;
}


void Nwidget::doconfigur_iserpixmapmode(QList<std::pair<NT::WIN_ATTRIBUTE, int>> insert_pixmapmode){
    impact_istpixmapmode["InsertModePair"] = insert_pixmapmode;
}


void Nwidget::doconfigur_secolor(QList<QList<QString>> secolor){
    QList<QList<QColor>>RecomBination;
    for (int index = 0;index < secolor.size(); index++){
        QList<QColor> ColorList;
        for (int itindex = 0; itindex < secolor[index].size(); itindex++){
            ColorList.append(QColor(secolor[index][itindex]));
        }
        RecomBination.append(ColorList);
    }
    impact_colorlist["mode-secolor"] = RecomBination;
}


void Nwidget::doconfigur_secolor(QList<QList<QColor>> secolor){
    impact_colorlist["mode-secolor"] = secolor;
}


void Nwidget::doconfigur_secolor(QList<QColor> secolor){
    impact_colorlist["mode-secolor"] = {secolor};
}


void Nwidget::doconfigur_secolor(QColor secolor){
    impact_colorlist["mode-secolor"] = QList<QList<QColor>>({{secolor}});
}


void Nwidget::doconfigur_pixmap(QVariant curtain, QSize fsize, bool hiq, int redius){
    QPixmap maskPixmap;
    bool load = PPScriptExec::pyScript_PixmapVariant(maskPixmap, curtain);
    setProperty("back-pixmap-fixedsize", fsize);
    setProperty("back-pixmap-radius", redius);
    setProperty("back-pixmap-hiq", hiq);
    setProperty("back-pixmap", maskPixmap);
    if (isVisible()) update_pixmap(size());
    if (!load) diary2("pixmap data load: ", curtain.toString().mid(0,120), Diary::Error)
}

void Nwidget::doconfigur_pixmap(QVariant curtain, QSize fsize){
    int redius = property("back-pixmap-radius").toInt();
    bool hiq = property("back-pixmap-hiq").toBool();
    doconfigur_pixmap(curtain, fsize, hiq, redius);
}

void Nwidget::doconfigur_pixmap(QVariant curtain){
    QSize fsize = property("back-pixmap-fixedsize").toSize();
    int redius = property("back-pixmap-radius").toInt();
    bool hiq = property("back-pixmap-hiq").toBool();
    doconfigur_pixmap(curtain, fsize, hiq, redius);
}

void Nwidget::doconfigur_pixmap(QSize fsize, bool hiq, int redius){
    setProperty("back-pixmap-fixedsize", fsize);
    setProperty("back-pixmap-radius", redius);
    setProperty("back-pixmap-hiq", hiq);
    if (isVisible()) update_pixmap(size());
}

void Nwidget::doconfigur_pixmap(int redius){
    setProperty("back-pixmap-radius", redius);
    if (isVisible()) update_pixmap(size());
}

void Nwidget::doconfigur_pixmap(QSize fsize){
    setProperty("back-pixmap-fixedsize", fsize);
    if (isVisible()) update_pixmap(size());
}

void Nwidget::paintEvent(QPaintEvent *){
    QPainter scdrpainter(this);
    scdrpainter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform);
    scdrpainter.setPen(Qt::NoPen);
    bool direction;
    if (static_cast<NT::CST_BRIGHT_SPOT>(property("direction").toInt()) == NT::ORIEN_HORIZONTAL)
    {
        direction = true;
    }
    else
    {
        direction = false;
    }
    if ((impact_colorlist["mode-secolor"].size() > 1 ||
         impact_colorlist["mode-secolor"][0].size() > 1) &&
         !property("back-pixmap").isValid()){
        scdrpainter.setPen(Qt::NoPen);
        QList<QList<QColor>> mode_secolor = impact_colorlist["mode-secolor"]; //#色段数据
        QLinearGradient Grandient; //#声明水平渐变类
        int IPTaddcount = 0; //#色段累计值，从0开始，完成一个QColor绘画则加1
        int StartLinearXpos = 0; //#水平渐变开始位置
        int EndLinearXpos = 0;  //#水平渐变结束位置
        int StartLinearYpos = 0;  //#垂直渐变开始位置
        int EndLinearYpos = 0;  //#垂直渐变结束位置
        int GlobalYstep = height() / mode_secolor.size(); //#垂直步长，即高除于色段数
        int GlobalXstep = width() / mode_secolor.size();  //#水平步长，即宽除于色段数
        for (int secNum = 0; secNum < mode_secolor.size(); secNum++){ //#循环色段数
            QList<std::pair<std::pair<QPixmap, int>, bool>> exceptivePixList; //#声明一个列表，用于收集图片
            QList<int> exceptiveIndexList;
            QRect SgSrcRect;
            EndLinearYpos += GlobalYstep; //#垂直渐变结束位置领先一个垂直步长
            EndLinearXpos += GlobalXstep; //#水平渐变结束位置领先一个水平步长
            //#定义渐变类，根据渐变方向参数设置开始和结束位置
            if (direction){
                Grandient = QLinearGradient(StartLinearXpos, 0, EndLinearXpos, 0);
            } else {
                Grandient = QLinearGradient(0, StartLinearYpos, 0, EndLinearYpos);
            }
            double DetailAddtion = 0; //#定义一个渐变步长累加浮点数
            //#定义一个相对色段步长，比如一个色段里面有3中颜色时，色段size为3，把色段分配的长度比做1，则相对步长为0.3，循环3次，则相对步长累加值 DetailAddtion
            //#分别为 0 0.3 0.6，而0.6往后是空的，也就是填不满，因此要在size的基础上减1，相对步长为0 0.5 1，才能实现渐变很好的填充
            double RelativeStep = 1.0 / (double)(mode_secolor[secNum].size() - 1);
            double StandardStep = 1.0 / (double)mode_secolor[secNum].size(); //#定义一个标准步长，也就是在size不减1的情况下的相对步长
            int DatailPptToWidthint = GlobalXstep * StandardStep; //#水平一个色号分配到的宽度
            int DatailPptToHeightint = GlobalYstep * StandardStep; //#垂直一个色号分配到的宽度
            int RationalSgExceptiveStart; //#定义一个色号开始绘画点
            QList<QString> pixkeys = impact_istpixmap.keys();
            for (int sgsec = 0; sgsec < mode_secolor[secNum].size(); sgsec++){ //#开始循环色段内的色号
                Grandient.setColorAt(DetailAddtion, mode_secolor[secNum][sgsec]); //#设置渐变步长累加值
                Grandient.setSpread(QGradient::ReflectSpread); //#设置渐变模式
                //#如果存在插入的图片或色号
                if (pixkeys.count("InsertPixmap") &&
                    !impact_istpixmap["InsertPixmap"].isEmpty()){
                    //#定义一个插入图片的数据列表
                    QList<std::pair<QString, int>> pixPairList = impact_istpixmap["InsertPixmap"];
                    for (int ist = 0; ist < pixPairList.size(); ist++){ //#循环插入数据
                        bool ratioMode=false; //#定义一个模式状态，不沿用 DescribeRatio 的状态了，当发生插入模式操作时， DescribeRatio 为备用状态，当前定义的才是主状态
                        QPixmap IstPixmap = pixPairList[ist].first; //#插入的数据
                        int InstIndex = pixPairList[ist].second;  //#插入数据对应的索引
                        if (!impact_istpixmapmode["InsertModePair"].isEmpty()) //#如果有插入模式数据
                        {
                            QList<std::pair<NT::WIN_ATTRIBUTE, int>> modeList = impact_istpixmapmode["InsertModePair"]; //#获取插入模式内容
                            for(int i = 0; i < modeList.size(); i++)
                            {
                                int indexOfmode = modeList[i].second; //#定义插入模式的索引
                                int modeName = modeList[i].first; //#定义插入模式名
                                if (indexOfmode == InstIndex) //#如果索引与当前索引一致，则使用插入的模式来进行图片的属性设置
                                {
                                    if (modeName == NT::PIXLOAD_KEEPRATIO)
                                    {
                                        ratioMode = true;
                                    }
                                    else
                                    {
                                        ratioMode = false;
                                    }
                                    break;
                                }
                            }
                        }
                        //#如果色号对应的索引与要插入的图片索引一致，并且图片还不为空
                        if (IPTaddcount == InstIndex && !IstPixmap.isNull()){
                            if (!direction){
                                //#计算垂直开始位置，分配到的高度 * 索引值 + 色段号 * 单个色段号对应的高
                                RationalSgExceptiveStart = DatailPptToHeightint * InstIndex + secNum * GlobalYstep;
                                if (ratioMode){
                                    //#维持比例模式下，计算图片比例，设置比例
                                    double PixPpt = IstPixmap.height() / DatailPptToHeightint;
                                    IstPixmap.setDevicePixelRatio(PixPpt);
                                }
                                else
                                {

                                    //#忽略比例模式下，设置pixmap为最大宽，高度为一个色号的高
                                    IstPixmap = IstPixmap.scaled(width(),
                                                                 DatailPptToHeightint,
                                                                 Qt::IgnoreAspectRatio,
                                                                 Qt::SmoothTransformation);
                                }
                            }
                            else
                            {
                                //#计算水平开始位置，分配到的宽度 * 索引值 + 色段号 * 单个色段号对应的宽
                                RationalSgExceptiveStart = DatailPptToWidthint * InstIndex + secNum * GlobalXstep;
                                if (ratioMode){
                                    //#维持比例模式下，计算图片比例，设置比例
                                    double PixPpt = IstPixmap.height() / height();
                                    IstPixmap.setDevicePixelRatio(PixPpt);
                                }
                                else
                                {
                                    //#忽略比例模式下，设置pixmap为最大高为组件高，宽度为一个色号的宽
                                    IstPixmap = IstPixmap.scaled(DatailPptToWidthint,
                                                                 height(),
                                                                 Qt::IgnoreAspectRatio,
                                                                 Qt::SmoothTransformation);
                                }
                            }
                            //#将数据装入容器，因为渐变在色段循环完毕后才设置完成，需要在后续brush才能生效，因此图片数据必须在绘制完渐变数据后才
                            //#开始进行插入，否则插入的图片将被渐变色号覆盖
                            exceptiveIndexList.append(InstIndex);
                            exceptivePixList.append(make_pair(std::make_pair(IstPixmap, RationalSgExceptiveStart), ratioMode));
                        }
                    }
                }
                IPTaddcount++; //#完成一个色号的渐变设置，累计值加1
                DetailAddtion += RelativeStep; //#完成一个色号的渐变设置，渐变步长累加浮点数累加一个相对步长
            }
            //#设置渐变矩形区域
            if (direction){
                SgSrcRect = QRect(StartLinearXpos, 0, EndLinearXpos, height());
            } else {
                SgSrcRect = QRect(0, StartLinearYpos, width(), EndLinearYpos);
            }
            //#绘画渐变
            scdrpainter.setBrush(Grandient);
            scdrpainter.drawRect(SgSrcRect);
            //#完成一个色段渐变的绘画则开始渐变累计值累加一个步长
            StartLinearXpos += GlobalXstep;
            StartLinearYpos += GlobalYstep;
            //#如果存在图片数据
            if (!exceptivePixList.isEmpty()){
                for (int pixNum = 0; pixNum < exceptivePixList.size(); pixNum++){
                    //#定义基础信息，起始绘画位置，图片，模式
                    int Begin = exceptivePixList[pixNum].first.second; //#图片开始绘画位置
                    QPixmap Pixmap = exceptivePixList[pixNum].first.first; //#图片
                    bool ratioMode = exceptivePixList[pixNum].second; //#模式
                    //# 通过比例得出宽高
                    int pixWidth = Pixmap.width() / Pixmap.devicePixelRatio();
                    int pixHeight = Pixmap.height() / Pixmap.devicePixelRatio();
                    //#声明和定义一个图片居中位置的坐标点
                    QPoint CentraHPos;
                    QPoint CentraVPos;
                    CentraHPos.setX((DatailPptToWidthint - pixWidth) / 2);
                    CentraHPos.setY((height() - pixHeight) / 2);
                    CentraVPos.setX((width() - pixWidth) / 2);
                    CentraVPos.setY((DatailPptToHeightint - pixHeight) / 2);
                    //#根据方向和模式开始绘画
                    if (direction)
                    {
                        if (ratioMode)
                        {
                            scdrpainter.drawPixmap(Begin + CentraHPos.x(), CentraHPos.y(), Pixmap);
                        }
                        else
                        {
                            scdrpainter.drawPixmap(Begin, 0, Pixmap);
                        }
                    }
                    else
                    {
                        if (ratioMode)
                        {
                            scdrpainter.drawPixmap(CentraVPos.x(), Begin + CentraVPos.y(), Pixmap);
                        }
                        else
                        {
                            scdrpainter.drawPixmap(0, Begin, Pixmap);
                        }
                    }
                }
            }
        }
    //#存在pixmap数据并且没有色段值或者色段值不符合时，执行以下代码
    } else {
        QPainterPath path;
        QPixmap maskPixmap = property("back-pixmap").value<QPixmap>();
        if (!maskPixmap.isNull())
        {
            QSize pixsize = maskPixmap.size();
            QSize bestsize = property("back-pixmap-fixedsize").value<QSize>();
            if (bestsize.isEmpty()) bestsize = size();
            QRect realrect((width() - pixsize.width()) / 2,
                           (height() - pixsize.height()) / 2,
                           bestsize.width(),
                           bestsize.height());
            path.addRoundedRect(realrect, property("back-pixmap-radius").toInt(), property("back-pixmap-radius").toInt());
            scdrpainter.setClipPath(path);
            scdrpainter.drawTiledPixmap(realrect, maskPixmap);
        }else{
            //#如果图片为空，则使用默认颜色
            QColor backcolor = impact_colorlist["mode-secolor"].first().first();
            scdrpainter.setBrush(backcolor);
            scdrpainter.drawRect(rect());
        }
    }
}


bool Nwidget::eventFilter(QObject *watched, QEvent *event){
    if (event->type() == QEvent::Resize)
    {
        QResizeEvent *cresize = static_cast<QResizeEvent*>(event);
        update_pixmap(cresize->size());
    }
    else if (event->type() == QEvent::MouseButtonPress)
    {
        QMouseEvent *smevpre = static_cast<QMouseEvent*>(event);
        emit msev_cspre(cursor());
        emit msev_pre(smevpre);
    }
    else if (event->type() == QEvent::CursorChange)
    {
        QMouseEvent *smevmv = static_cast<QMouseEvent*>(event);
        emit msev_mv(smevmv);
    }
    else if (event->type() == QEvent::MouseButtonRelease)
    {
        QMouseEvent *smevrls = static_cast<QMouseEvent*>(event);
        emit msev_rls(smevrls);
        emit msnm_rls(objectName());
    }
    else if (event->type() == QEvent::Enter)
    {
        emit msev_etr(std::make_pair(true, objectName()));
        if (property("mode-autoclose").toBool() && autoTimer.isActive())
        {
            autoTimer.stop();
        }
    }
    else if (event->type() == QEvent::Leave)
    {
        emit msev_lve(std::make_pair(false, objectName()));
        if (property("mode-autoclose").toBool())
        {
            autoTimer.start(property("mode-autoclosewait").toInt());
        }
    }
    return QWidget::eventFilter(watched, event);
}


void Nwidget::setVisible(bool visible){
    QWidget::setVisible(visible);
    if (property("mode-autoclose").toBool())
    {
        autoTimer.start(property("mode-autoclosewait").toInt());
    }
}


void Nwidget::doconfigur_iserpixmapdel(){
    setProperty("InsertPixmap", QPixmap());
}


void Nwidget::doconfigur_secolordel(){
    impact_colorlist["mode-secolor"].clear();
}


void Nwidget::update_pixmap(QSize adjusted){
    QPixmap maskPixmap = property("back-pixmap").value<QPixmap>();
    if (!maskPixmap.isNull() && maskPixmap.size() != size())
    {
        QSize fsize = property("back-pixmap-fixedsize").value<QSize>();
        bool hiq = property("back-pixmap-hiq").toBool();
        if (objectName() == "555") qDebug() << fsize;
        PPScriptExec::pyScript_PixmapVariant(adjusted, maskPixmap, fsize, hiq);
        setProperty("back-pixmap", maskPixmap);
        update();
    }
}
